//==========================================================================
// Copyright (c) 2000-2006,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

//#include <xllp_lcd.h>
#include "xllp_lcd.h"
#include "display_def.h"
#include <util.h>
#include "hardware.h"
#include <bitfield.h>
#if 1
#define LCCR0		__REG_2(0x44000000)	/* LCD Controller Control Register 0 */
#define LCCR1		__REG_2(0x44000004)	/* LCD Controller Control Register 1 */
#define LCCR2		__REG_2(0x44000008)	/* LCD Controller Control Register 2 */
#define LCCR3		__REG_2(0x4400000C)	/* LCD Controller Control Register 3 */
#define LCCR4		__REG_2(0x44000010)	/* LCD Controller Control Register 4 */
#define LCCR5		__REG_2(0x44000014)	/* LCD Controller Control Register 5 */
#define LCCR6		__REG_2(0x44000018)	/* LCD Controller Control Register 6 */
#define DFBR0		__REG_2(0x44000020)	/* DMA Channel 0 Frame Branch Register */
#define DFBR1		__REG_2(0x44000024)	/* DMA Channel 1 Frame Branch Register */
#define LCSR		__REG_2(0x44000038)	/* LCD Controller Status Register */
#define LCSR1		__REG_2(0x44000034)	/* LCD Controller Status Register */
#define LIIDR		__REG_2(0x4400003C)	/* LCD Controller Interrupt ID Register */
#define TMEDRGBR	__REG_2(0x44000040)	/* TMED RGB Seed Register */
#define TMEDCR		__REG_2(0x44000044)	/* TMED Control Register */

#define LCCR3_1BPP (0)
#define LCCR3_2BPP (1)
#define LCCR3_4BPP (2)
#define LCCR3_8BPP (3)
#define LCCR3_16BPP (4)
#define LCCR3_18BPP (6)       	/* packed pixel format */
#define LCCR3_19BPP (8)       	/* packed pixel format */
#define LCCR3_24BPP (9)
#define LCCR3_25BPP (10)

#define LCCR4_REOFM0	(1 << 9)
#define LCCR4_REOFM1	(1 << 10)
#define LCCR4_REOFM2	(1 << 11)
#define LCCR4_REOFM3	(1 << 12)
#define LCCR4_REOFM4	(1 << 13)
#define LCCR4_REOFM5	(1 << 14)
#define LCCR4_REOFM6	(1 << 26)
#define LCCR4_PCDDIV	(1 << 31)

/* Overlay1 & Overlay2 & Hardware Cursor */
#define LCSR1_SOF1	(1 << 0)
#define LCSR1_SOF2	(1 << 1)
#define LCSR1_SOF3	(1 << 2)
#define LCSR1_SOF4	(1 << 3)
#define LCSR1_SOF5	(1 << 4)
#define LCSR1_SOF6	(1 << 5)

#define LCSR1_EOF1	(1 << 8)
#define LCSR1_EOF2	(1 << 9)
#define LCSR1_EOF3	(1 << 10)
#define LCSR1_EOF4	(1 << 11)
#define LCSR1_EOF5	(1 << 12)
#define LCSR1_EOF6	(1 << 13)

#define LCSR1_BS1	(1 << 16)
#define LCSR1_BS2	(1 << 17)
#define LCSR1_BS3	(1 << 18)
#define LCSR1_BS4	(1 << 19)
#define LCSR1_BS5	(1 << 20)
#define LCSR1_BS6	(1 << 21)

#define LCSR1_IU2	(1 << 25)
#define LCSR1_IU3	(1 << 26)
#define LCSR1_IU4	(1 << 27)
#define LCSR1_IU5	(1 << 28)
#define LCSR1_IU6	(1 << 29)

#define LDCMD_SOFINT	(1 << 22)
#define LDCMD_EOFINT	(1 << 21)

#define LCCR5_SOFM1	(1<<0)		/* Start Of Frame Mask for Overlay 1 (channel 1) */
#define LCCR5_SOFM2	(1<<1)		/* Start Of Frame Mask for Overlay 2 (channel 2) */
#define LCCR5_SOFM3	(1<<2)		/* Start Of Frame Mask for Overlay 2 (channel 3) */
#define LCCR5_SOFM4	(1<<3)		/* Start Of Frame Mask for Overlay 2 (channel 4) */
#define LCCR5_SOFM5	(1<<4)		/* Start Of Frame Mask for cursor (channel 5) */
#define LCCR5_SOFM6	(1<<5)		/* Start Of Frame Mask for command data (channel 6) */

#define LCCR5_EOFM1	(1<<8)		/* End Of Frame Mask for Overlay 1 (channel 1) */
#define LCCR5_EOFM2	(1<<9)		/* End Of Frame Mask for Overlay 2 (channel 2) */
#define LCCR5_EOFM3	(1<<10)		/* End Of Frame Mask for Overlay 2 (channel 3) */
#define LCCR5_EOFM4	(1<<11)		/* End Of Frame Mask for Overlay 2 (channel 4) */
#define LCCR5_EOFM5	(1<<12)		/* End Of Frame Mask for cursor (channel 5) */
#define LCCR5_EOFM6	(1<<13)		/* End Of Frame Mask for command data (channel 6) */

#define LCCR5_BSM1	(1<<16)		/* Branch mask for Overlay 1 (channel 1) */
#define LCCR5_BSM2	(1<<17)		/* Branch mask for Overlay 2 (channel 2) */
#define LCCR5_BSM3	(1<<18)		/* Branch mask for Overlay 2 (channel 3) */
#define LCCR5_BSM4	(1<<19)		/* Branch mask for Overlay 2 (channel 4) */
#define LCCR5_BSM5	(1<<20)		/* Branch mask for cursor (channel 5) */
#define LCCR5_BSM6	(1<<21)		/* Branch mask for data command  (channel 6) */

#define LCCR5_IUM1	(1<<24)		/* Input FIFO Underrun Mask for Overlay 1  */
#define LCCR5_IUM2	(1<<25)		/* Input FIFO Underrun Mask for Overlay 2  */
#define LCCR5_IUM3	(1<<26)		/* Input FIFO Underrun Mask for Overlay 2  */
#define LCCR5_IUM4	(1<<27)		/* Input FIFO Underrun Mask for Overlay 2  */
#define LCCR5_IUM5	(1<<28)		/* Input FIFO Underrun Mask for cursor */
#define LCCR5_IUM6	(1<<29)		/* Input FIFO Underrun Mask for data command */

#define OVL1C1_O1EN	(1<<31)		/* Enable bit for Overlay 1 */
#define OVL2C1_O2EN	(1<<31)		/* Enable bit for Overlay 2 */
#define CCR_CEN		(1<<31)		/* Enable bit for Cursor */

#define FDADR0		__REG_2(0x44000200)	/* DMA Channel 0 Frame Descriptor Address Register */
#define FSADR0		__REG_2(0x44000204)	/* DMA Channel 0 Frame Source Address Register */
#define FIDR0		__REG_2(0x44000208)	/* DMA Channel 0 Frame ID Register */
#define LDCMD0		__REG_2(0x4400020C)	/* DMA Channel 0 Command Register */
#define FDADR1		__REG_2(0x44000210)	/* DMA Channel 1 Frame Descriptor Address Register */
#define FSADR1		__REG_2(0x44000214)	/* DMA Channel 1 Frame Source Address Register */
#define FIDR1		__REG_2(0x44000218)	/* DMA Channel 1 Frame ID Register */
#define LDCMD1		__REG_2(0x4400021C)	/* DMA Channel 1 Command Register */

#define FBR0		__REG_2(0x44000020)	/* DMA Channel 0 Frame Branch Register */
#define FBR1		__REG_2(0x44000024)	/* DMA Channel 1 Frame Branch Register */
#define FBR2		__REG_2(0x44000028)	/* DMA Channel 2 Frame Branch Register */
#define FBR3		__REG_2(0x4400002C)	/* DMA Channel 3 Frame Branch Register */
#define FBR4		__REG_2(0x44000030)	/* DMA Channel 4 Frame Branch Register */
#define FDADR2		__REG_2(0x44000220)	/* DMA Channel 2 Frame Descriptor Address Register */
#define FSADR2		__REG_2(0x44000224)	/* DMA Channel 2 Frame Source Address Register */
#define FIDR2		__REG_2(0x44000228)	/* DMA Channel 2 Frame ID Register */
#define LDCMD2		__REG_2(0x4400022C)	/* DMA Channel 2 Command Register */
#define FDADR3		__REG_2(0x44000230)	/* DMA Channel 3 Frame Descriptor Address Register */
#define FSADR3		__REG_2(0x44000234)	/* DMA Channel 3 Frame Source Address Register */
#define FIDR3		__REG_2(0x44000238)	/* DMA Channel 3 Frame ID Register */
#define LDCMD3		__REG_2(0x4400023C)	/* DMA Channel 3 Command Register */
#define FDADR4		__REG_2(0x44000240)	/* DMA Channel 4 Frame Descriptor Address Register */
#define FSADR4		__REG_2(0x44000244)	/* DMA Channel 4 Frame Source Address Register */
#define FIDR4		__REG_2(0x44000248)	/* DMA Channel 4 Frame ID Register */
#define LDCMD4		__REG_2(0x4400024C)	/* DMA Channel 4 Command Register */
#define FDADR5		__REG_2(0x44000250)	/* DMA Channel 5 Frame Descriptor Address Register */
#define FSADR5		__REG_2(0x44000254)	/* DMA Channel 5 Frame Source Address Register */
#define FIDR5		__REG_2(0x44000258)	/* DMA Channel 5 Frame ID Register */
#define LDCMD5		__REG_2(0x4400025C)	/* DMA Channel 5 Command Register */

#define OVL1C1		__REG_2(0x44000050)	/* Overlay 1 Control Register 1 */
#define OVL1C2		__REG_2(0x44000060)	/* Overlay 1 Control Register 2 */
#define OVL2C1		__REG_2(0x44000070)	/* Overlay 2 Control Register 1 */
#define OVL2C2		__REG_2(0x44000080)	/* Overlay 2 Control Register 2 */
#define CCR		__REG_2(0x44000090)	/* Cursor Control Register */

#define FBR5		__REG_2(0x44000110)	/* DMA Channel 5 Frame Branch Register */
#define FBR6		__REG_2(0x44000114)	/* DMA Channel 6 Frame Branch Register */

#define FDADR6         __REG_2(0x44000260)  /* DMA Channel 6 Frame Descriptor Address Register */
#define CMDCR          __REG_2(0x44000100)  /*Command Control Register*/
#define PRSR           __REG_2(0x44000104)  /*Command Control Register*/

#define MLCCR0		__REG_2(0x46000000)	/* Mini-LCD Controller Control Register 0 */
#define MLCCR1		__REG_2(0x46000004)	/* Mini-LCD Controller Control Register 1 */
#define MLCCR2		__REG_2(0x46000008)	/* Mini-LCD Controller Control Register 2 */
#define MLSADD		__REG_2(0x4600000C)	/* Mini-LCD SRAM Address Register */
#define MLFRMCNT	__REG_2(0x46000010)	/* Mini-LCD Frame Count Register */


#define ACCR		__REG(0x41340000)	/* Application Subsystem Clock Configuration Register */
#define ACSR		__REG(0x41340004)	/* Application Subsystem Clock Status Register */
#define AICSR		__REG(0x41340008)	/* Application Subsystem Interrupt Control/Status Register */
#define CKENA		__REG(0x4134000C)	/* A Clock Enable Register */
#define CKENB		__REG(0x41340010)	/* B Clock Enable Register */
#define AC97_DIV	__REG(0x41340014)	/* AC97 clock divisor value register */
#define OSCC		__REG(0x41350000)	/* Oscillator Configuration Register */

#define	CKEN_LCD	1	/* < LCD Clock Enable */
#define LDCMD_EOFINT	(1 << 21)
#define LCCR0_ENB	(1 << 0)	/* LCD Controller enable */



/////////////
//
// LCD Controller DMA Frame Descriptor Address Registers (FDADRx)
//
#define XLLP_FDADR_DESCADDR(n)	((n) & 0xFFFFFFF0)

//
// LCD Controller DMA Frame Source Address Registers (FSADRx)
//
#define XLLP_FSADR_SRCADDR(n)	((n) & 0xFFFFFFF8)

//
// LCD Controller DMA Frame ID Registers (FIDRx)
//
#define XLLP_FIDR_FRAMEID(n)		((n) & 0xFFFFFFF8)

//
// LCD Controller DMA Command Registers (LDCMDx)
//
#define XLLP_LDCMD_LEN(n)			((n)&0x1ffffc)
#define XLLP_LDCMD_EOFINT			(0x1u<<21)
#define XLLP_LDCMD_SOFINT			(0x1u<<22)
#define XLLP_LDCMD_LSTDES_EN_MASK	(0x3u<<23)
#define XLLP_LDCMD_PAL				(0x1u<<26)

//
// LCD Controller DMA Frame Branch Registers (FBRx)
//
#define XLLP_FBR_BRA		(0x1u<<0)
#define XLLP_FBR_BINT		(0x1u<<1)
#define XLLP_FBR_SRCADDR(n)	((n)&0xfffffff0)

//////////////

#endif				/* CONFIG_PXA3xx */

void DumpLcdControllerRegs()
{
#if 0
    printk("dump lcd:\n");
    printk("LCCR0=%08x\n", LCCR0);
    printk("LCCR1=%08x\n", LCCR1);
    printk("LCCR2=%08x\n", LCCR2);
    printk("LCCR3=%08x\n", LCCR3);
    printk("LCCR4=%08x\n", LCCR4);
    printk("LCCR5=%08x\n", LCCR5);

    printk("OVL1C1=%08x\n", OVL1C1);
    printk("OVL1C2=%08x\n", OVL1C2);
    printk("OVL2C1=%08x\n", OVL2C1);
    printk("OVL2C2=%08x\n", OVL2C2);
#endif

}

static void LCDClearStatusReg()
{
    // Clear the status registers by writing 1's to each bit.
    LCSR =  ( XLLP_LCSR0_LDD | XLLP_LCSR0_SOF0  | XLLP_LCSR0_BER | XLLP_LCSR0_ABC  | XLLP_LCSR0_IU0 |
        XLLP_LCSR0_IU1 | XLLP_LCSR0_OU    | XLLP_LCSR0_QD  | XLLP_LCSR0_EOF0 | XLLP_LCSR0_BS0 |
        XLLP_LCSR0_SINT| XLLP_LCSR0_RD_ST | XLLP_LCSR0_CMD_INTR |
        XLLP_LCSR0_REOF0| XLLP_LCSR0_REOF1|XLLP_LCSR0_REOF2|XLLP_LCSR0_REOF3 |XLLP_LCSR0_REOF4|XLLP_LCSR0_REOF5 |XLLP_LCSR0_REOF6 );
    LCSR1 =  ( XLLP_LCSR1_SOF1| XLLP_LCSR1_SOF2 | XLLP_LCSR1_SOF3| XLLP_LCSR1_SOF4| XLLP_LCSR1_SOF5  | XLLP_LCSR1_SOF6   |
        XLLP_LCSR1_EOF1| XLLP_LCSR1_EOF2 | XLLP_LCSR1_EOF3| XLLP_LCSR1_EOF4| XLLP_LCSR1_EOF5  | XLLP_LCSR1_EOF6   |
        XLLP_LCSR1_BS1 | XLLP_LCSR1_BS2  | XLLP_LCSR1_BS3 | XLLP_LCSR1_BS4 | XLLP_LCSR1_BS5   | XLLP_LCSR1_BS6    |
        XLLP_LCSR1_IU2  | XLLP_LCSR1_IU3 | XLLP_LCSR1_IU4 | XLLP_LCSR1_IU5   | XLLP_LCSR1_IU6 );
}

// Use the following for hss values of XllpLCDAdjustPCD
#define HSS_104M			0x0
#define HSS_156M			0x1
#define HSS_208M			0x2
#define HSS_AUTO_DETECT		0x4


// PCD values for LTM035A776C
// FIX ME: Update these values according real visual effect!
// Pixel clock of LTM035A776C should be 9.10 MHz
// In theory, PCD_HSS_104M = 104/9.10 - 1 = 10.43
#define PCD_HSS_104M	10
#define PCD_HSS_156M	16
#define PCD_HSS_208M	20
#define PCD_MLCD_39M	4

#define HSS_D0CS	0x3

void XllpLCDAdjustPCD()
{
    int hss;
    //acsr: ///< Application Subsystem Clock Status register
    if (1) {
        if (ACSR & 0x04000000)
            hss = HSS_D0CS;
        else
            hss = (ACSR & 0xc000) >> 14;
    }
    XLLP_UINT32_T pcd;
    switch (hss) {
        case HSS_104M:
            pcd = PCD_HSS_104M;
            break;
        case HSS_156M:
            pcd = PCD_HSS_156M;///////
            break;
        case HSS_208M:
            pcd = PCD_HSS_208M;
            break;
        default:
            pcd = PCD_HSS_208M;
            break;
    }
    LCCR4 |= XLLP_LCCR4_PIX_DIV_EQ;
    LCCR3 = (LCCR3 & (~XLLP_LCCR3_PCD_MASK))|pcd;
    return;
}

//set lccr1:
#define LCCR1_PPL       Fld (10, 0)      /* Pixels Per Line - 1 */
#define LCCR1_DisWdth(Pixel)            /* Display Width [1..800 pix.]  */ \
                        (((Pixel) - 1) << FShft (LCCR1_PPL))

#define LCCR1_HSW       Fld (6, 10)     /* Horizontal Synchronization     */
#define LCCR1_HorSnchWdth(Tpix)         /* Horizontal Synchronization     */ \
                                        /* pulse Width [1..64 Tpix]       */ \
                        (((Tpix) - 1) << FShft (LCCR1_HSW))

#define LCCR1_BLW       Fld (8, 24)     /* Beginning-of-Line pixel clock   */
                                        /* Wait count - 1 [Tpix]           */
#define LCCR1_BegLnDel(Tpix)            /*  Beginning-of-Line Delay        */ \
                                        /*  [1..256 Tpix]                  */ \
                        (((Tpix) - 1) << FShft (LCCR1_BLW))

#define LCCR1_ELW       Fld (8, 16)     /* End-of-Line pixel clock Wait    */
                                        /* count - 1 [Tpix]                */
#define LCCR1_EndLnDel(Tpix)            /*  End-of-Line Delay              */ \
                                        /*  [1..256 Tpix]                  */ \
                        (((Tpix) - 1) << FShft (LCCR1_ELW))

//set lccr2:
#define LCCR2_LPP       Fld (10, 0)     /* Line Per Panel - 1              */
#define LCCR2_DisHght(Line)             /*  Display Height [1..1024 lines] */ \
                        (((Line) - 1) << FShft (LCCR2_LPP))

#define LCCR2_VSW       Fld (6, 10)     /* Vertical Synchronization pulse  */
                                        /* Width - 1 [Tln] (L_FCLK)        */
#define LCCR2_VrtSnchWdth(Tln)          /*  Vertical Synchronization pulse */ \
                                        /*  Width [1..64 Tln]              */ \
                        (((Tln) - 1) << FShft (LCCR2_VSW))

#define LCCR2_EFW       Fld (8, 16)     /* End-of-Frame line clock Wait    */
                                        /* count [Tln]                     */
#define LCCR2_EndFrmDel(Tln)            /*  End-of-Frame Delay             */ \
                                        /*  [0..255 Tln]                   */ \
                        ((Tln) << FShft (LCCR2_EFW))

#define LCCR2_BFW       Fld (8, 24)     /* Beginning-of-Frame line clock   */
                                        /* Wait count [Tln]                */
#define LCCR2_BegFrmDel(Tln)            /*  Beginning-of-Frame Delay       */ \
                                        /*  [0..255 Tln]                   */ \
                        ((Tln) << FShft (LCCR2_BFW))

//set lccr3:
/*
 *  pxafb_bpp_to_lccr3():
 *    Convert a bits per pixel value to the correct bit pattern for LCCR3
 */
 #define LCCR3_BPP       Fld (3, 24)     /* Bit Per Pixel */
#define LCCR3_Bpp(Bpp)                  /* Bit Per Pixel */ \
                        (((((Bpp) & 7 ) << FShft (LCCR3_BPP))) | (((Bpp) & 8) << 26))

static int pxafb_bpp_to_lccr3(int bits_per_pixel)
{
        int ret = 0;
        switch (bits_per_pixel) {
        case 1:  ret = LCCR3_1BPP; break;
        case 2:  ret = LCCR3_2BPP; break;
        case 4:  ret = LCCR3_4BPP; break;
        case 8:  ret = LCCR3_8BPP; break;
        case 16: ret = LCCR3_16BPP; break;
        case 18: ret = LCCR3_18BPP; break;
        case 19: ret = LCCR3_19BPP; break;
        case 24: ret = LCCR3_24BPP; break;
        case 25: ret = LCCR3_25BPP; break;
        }
        return LCCR3_Bpp(ret);
}
#define LCCR3_VSP	(1 << 20)	/* vertical sync polarity */
#define LCCR3_HSP	(1 << 21)	/* horizontal sync polarity */


#define FB_SYNC_HOR_HIGH_ACT	1	/* horizontal sync high active	*/
#define FB_SYNC_VERT_HIGH_ACT	2	/* vertical sync high active	*/

#define LCCR3_HorSnchH  (LCCR3_HSP*0)   /*  Horizontal Synchronization     */
                                        /*  pulse active High              */
#define LCCR3_HorSnchL  (LCCR3_HSP*1)   /*  Horizontal Synchronization     */

#define LCCR3_VrtSnchH  (LCCR3_VSP*0)   /*  Vertical Synchronization pulse */
                                        /*  active High                    */
#define LCCR3_VrtSnchL  (LCCR3_VSP*1)   /*  Vertical Synchronization pulse */

/*
 * Return the current LCD clock frequency in units of 10kHz as
 * LCLK is from High Speed IO Bus Clock
 */
 #define ACSR_D0CS	(1 << 26)
#define ACSR_HSIO_MASK	0x0000c000	/* High Speed IO Frequency Select */

unsigned int get_lcdclk_frequency_10khz(void)
{
	unsigned long acsr_val;
	int s_clk=0, HSS;

	acsr_val = ACSR;
	if (acsr_val & ACSR_D0CS) {
		/* Ring Oscillator mode */
		s_clk = 60;
	} else {
		HSS = (acsr_val & ACSR_HSIO_MASK) >> 14;
		switch (HSS) {
		case 0:
			s_clk = 104;
			break;
		case 1:
			s_clk = 156;
			break;
		case 2:
			s_clk = 208;
			break;
		default:
			break;
		}
	}
	return (s_clk * 100);
}

/*
 * Calculate the PCD value from the clock rate (in picoseconds).
 * We take account of the PPCR clock setting.
 * From PXA Developer's Manual:
 *
 *   PixelClock =      LCLK
 *                -------------
 *                2 ( PCD + 1 )
 *
 *   PCD =      LCLK
 *         ------------- - 1
 *         2(PixelClock)
 *
 * Where:
 *   LCLK = LCD/Memory Clock
 *   PCD = LCCR3[7:0]
 *
 * PixelClock here is in Hz while the pixclock argument given is the
 * period in picoseconds. Hence PixelClock = 1 / ( pixclock * 10^-12 )
 *
 * The function get_lclk_frequency_10khz returns LCLK in units of
 * 10khz. Calling the result of this function lclk gives us the
 * following
 *
 *    PCD = (lclk * 10^4 ) * ( pixclock * 10^-12 )
 *          -------------------------------------- - 1
 *                          2
 *
 * Factoring the 10^4 and 10^-12 out gives 10^-8 == 1 / 100000000 as used below.
 */
  static inline unsigned int do_div(unsigned long long n, unsigned int  base)
 {
       unsigned int  remainder = n % base;
       n = n / base;
        return remainder;
  }
static inline unsigned int __get_pcd(unsigned long long lclk, unsigned int pixclock)
{
	unsigned long long pcd;
	unsigned long long remainder;

	/* FIXME: Need to take into account Double Pixel Clock mode
         * (DPC) bit? or perhaps set it based on the various clock
         * speeds */

	pcd = (unsigned long long)lclk*pixclock;

	if (LCCR4 & LCCR4_PCDDIV) {
		remainder = do_div(pcd, 100000000);
		if (remainder < 50000000)
			pcd -= 1;
	}
	else {
		remainder = do_div(pcd, 100000000 * 2);
		if (remainder < 100000000)
			pcd -= 1;
	}

	/* FIXME: for lcd clock(10khz) equals 10400 or 5200, special
	   PCD value is used. If we use the formula to calculate the
	   PCD value, the LCD will flicker when DVFM.
	*/
	return (unsigned int)pcd;
}


#define LCCR3_PCD       Fld (8, 0)      /* Pixel Clock Divisor */
#define LCCR3_PixClkDiv(Div)            /* Pixel Clock Divisor */ \
                        (((Div) << FShft (LCCR3_PCD)))



static inline unsigned int get_pcd(unsigned int pixclock)
{
	unsigned long long lclk = get_lcdclk_frequency_10khz();
	return __get_pcd(lclk, pixclock);
}


void LcdCtrl_Init(DisplayContext *pCxt)
{
    int PixelDataFormat;

    pxa_set_cken(CKEN_LCD, 0);

    if (pCxt->basePlaneFormat == COLOR_RGB565) {
        PixelDataFormat = PDFOR_00;
    }
    else {
        PixelDataFormat = PDFOR_11; // RGBT555
    }

    // Determine the frame buffer size for the DMA transfer length.
    // Scale the size based on the bpp of the frame buffer to determine
    // an actual size in bytes
    int FrameBufferSize = LCD_WIDTH * LCD_HEIGHT;
    FrameBufferSize <<= 1; // 16BPP

    //////////////////////////////////////has update
    LCD_FRAME_DESCRIPTOR *frameDescriptorCh0fd1 = (LCD_FRAME_DESCRIPTOR *)pCxt->vaChan0Desc;

    // Configure the general purpose frame descriptors
    // Set the physical address of the frame descriptor
    frameDescriptorCh0fd1->FDADR = XLLP_FDADR_DESCADDR(pCxt->paChan0Desc);
    // Set the physical address of the frame buffer
    frameDescriptorCh0fd1->FSADR = XLLP_FSADR_SRCADDR(pCxt->paBasePlane);
    // Clear the frame ID
    frameDescriptorCh0fd1->FIDR  = XLLP_FIDR_FRAMEID(0);

    // Set the DMA transfer length to the size of the frame buffer
    frameDescriptorCh0fd1->LDCMD = XLLP_LDCMD_LEN(FrameBufferSize); //| LDCMD_EOFINT;
    // Store the physical address of this frame descriptor in the frame descriptor
    frameDescriptorCh0fd1->PHYSADDR = frameDescriptorCh0fd1->FDADR;
    // FBR0 is cleared and is not used.
    FBR0 = 0;

    // Load the contents of FDADR0 with the physical address of this frame descriptor
    FDADR0 = XLLP_FDADR_DESCADDR(frameDescriptorCh0fd1->FDADR);

    //lccr0-4 will be configured by platform-specific code.
    int BPP = 4; // BPP_16;
    LCCR0 = 0;
    LCCR1 = 0;
    LCCR2 = 0;
    LCCR3 = XLLP_LCCR3_BPP(BPP);

    LCCR4 |= (1 << 31);

    LCCR4 = XLLP_LCCR4_REOFM0|XLLP_LCCR4_REOFM1|XLLP_LCCR4_REOFM2|XLLP_LCCR4_REOFM3|XLLP_LCCR4_REOFM4|XLLP_LCCR4_REOFM5|XLLP_LCCR4_REOFM6;
    LCCR5 = (XLLP_LCCR5_SOFM1|XLLP_LCCR5_SOFM2|XLLP_LCCR5_SOFM3|XLLP_LCCR5_SOFM4|XLLP_LCCR5_SOFM5|XLLP_LCCR5_SOFM6|
        XLLP_LCCR5_EOFM1|XLLP_LCCR5_EOFM2|XLLP_LCCR5_EOFM3|XLLP_LCCR5_EOFM4|XLLP_LCCR5_EOFM5|XLLP_LCCR5_EOFM6|
        XLLP_LCCR5_BSM1 |XLLP_LCCR5_BSM2 |XLLP_LCCR5_BSM3 |XLLP_LCCR5_BSM4 |XLLP_LCCR5_BSM5 |XLLP_LCCR5_BSM6 |
        XLLP_LCCR5_IUM1 |XLLP_LCCR5_IUM2 |XLLP_LCCR5_IUM3 |XLLP_LCCR5_IUM4 |XLLP_LCCR5_IUM5 |XLLP_LCCR5_IUM6 );

    LCCR6 = 0;

    // Enable the LCD
    //    CKENAA |= (0x1U <<1) ;

    /* Enable Chroma Key */
    LCCR3 &= ~0xc0000000;
    LCCR4 |= (1 << 30) | (1 << 27);

    LCCR4 = LCCR4 | 0x000001ff;

    // Panel-specific LCD controller initialization
    // LTM035A776C: 240x320 16bpp active matrix
    LCCR0 |= (XLLP_LCCR0_LDM | XLLP_LCCR0_SOFM0 | XLLP_LCCR0_IUM | XLLP_LCCR0_EOFM0 |
        XLLP_LCCR0_PAS | XLLP_LCCR0_QDM | XLLP_LCCR0_BSM0  | XLLP_LCCR0_OUM |
        XLLP_LCCR0_RDSTM | XLLP_LCCR0_CMDIM | /*XLLP_LCCR0_OUC | */XLLP_LCCR0_LDDALT);
#if 0 //CONFIG_FB_PXA_LCD_QVGA
static struct pxafb_mach_info tpo_tdo24mtea1_qvga __initdata = {
	.pixclock		= 153000,
	.xres			= 240,
	.yres			= 320,
	.bpp			= 16,
	.hsync_len		= 8,
	.left_margin		= 8,
	.right_margin		= 88,
	.vsync_len		= 2,
	.upper_margin		= 2,
	.lower_margin		= 2,
	.sync			= 0,
	.lccr0			= LCCR0_Act,
	.lccr3			= LCCR3_HSP | LCCR3_VSP,
	.pxafb_backlight_power	= littleton_backlight_power,
	.pxafb_lcd_power	= littleton_lcd_power,
};
#endif

  unsigned int lccr1, lccr2, lccr3;
   lccr1 =
		LCCR1_DisWdth(240) +
		LCCR1_HorSnchWdth(8) +
		LCCR1_BegLnDel(0) +//8
		LCCR1_EndLnDel(0);//88
   LCCR1 = lccr1;

   lccr2 = LCCR2_DisHght(320) + LCCR2_VrtSnchWdth(2) + LCCR2_BegFrmDel(0) + LCCR2_EndFrmDel(0);
   LCCR2 = lccr2;

    int sync = 1;
    lccr3 = LCCR3_HSP | LCCR3_VSP;
    lccr3 = lccr3 |pxafb_bpp_to_lccr3(16) |
    	(sync & FB_SYNC_HOR_HIGH_ACT ? LCCR3_HorSnchH : LCCR3_HorSnchL) |
    	(sync & FB_SYNC_VERT_HIGH_ACT ? LCCR3_VrtSnchH : LCCR3_VrtSnchL) ;

 //   if (pcd)
 //   	lccr3 |= LCCR3_PixClkDiv(pcd);
     LCCR3 = lccr3;

    LCCR4 |= XLLP_LCCR4_PAL_FOR(0);


    /* Enable Chroma Key */
    LCCR3 &= ~0xc0000000;
    LCCR4 |= (1 << 30) | (1 << 27);

    LCCR0 |= LCCR0_ENB;
    /* enable LCD controller clock */
    pxa_set_cken(CKEN_LCD, 1);


    XllpLCDAdjustPCD();

    // Clear LCD Controller status register
    LCDClearStatusReg();

}

void LcdCtrl_Enable(DisplayContext *pCxt)
{
    LCCR0 |= LCCR0_ENB;
    DumpLcdControllerRegs();
}

void LcdCtrl_Disable(DisplayContext *pCxt)
{
    LCCR0 &= ~LCCR0_ENB;
}

